# -*- coding: utf-8 -*-
"""
文件树数据模型模块
实现远程文件列表的数据模型，支持文件显示、选择和操作
"""

from PySide2.QtCore import QAbstractTableModel, Qt, QModelIndex, Signal, QMimeData
from PySide2.QtGui import QIcon, QPixmap
from PySide2.QtWidgets import QApplication
from datetime import datetime
import os
from pathlib import Path
from gglobal import logger


class FileInfo:
    """文件信息类"""
    
    def __init__(self, name="", size=0, modified_time=None, permissions="", owner="", is_directory=False, is_parent=False):
        self.name = name
        self.size = size
        self.modified_time = modified_time or datetime.now()
        self.permissions = permissions
        self.owner = owner
        self.is_directory = is_directory
        self.is_parent = is_parent  # 是否为返回上级目录项
        
    def get_size_string(self):
        """获取格式化的文件大小字符串"""
        if self.is_directory or self.is_parent:
            return ""
            
        if self.size < 1024:
            return f"{self.size} B"
        elif self.size < 1024 * 1024:
            return f"{self.size / 1024:.1f} KB"
        elif self.size < 1024 * 1024 * 1024:
            return f"{self.size / (1024 * 1024):.1f} MB"
        else:
            return f"{self.size / (1024 * 1024 * 1024):.1f} GB"
            
    def get_time_string(self):
        """获取格式化的时间字符串"""
        if self.is_parent:
            return ""
        return self.modified_time.strftime("%Y-%m-%d %H:%M:%S")
        
    def get_icon_name(self):
        """根据文件类型获取图标名称"""
        if self.is_parent:
            return "blackfolder"
        elif self.is_directory:
            return "folder"
        else:
            # 根据文件扩展名返回不同图标
            ext = Path(self.name).suffix.lower()
            if ext in ['.txt', '.log', '.md']:
                return "text"
            elif ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']:
                return "image"
            elif ext in ['.mp4', '.avi', '.mkv', '.mov']:
                return "video"
            elif ext in ['.mp3', '.wav', '.flac', '.aac']:
                return "audio"
            elif ext in ['.zip', '.rar', '.7z', '.tar', '.gz']:
                return "archive"
            elif ext in ['.pdf']:
                return "pdf"
            elif ext in ['.doc', '.docx']:
                return "word"
            elif ext in ['.xls', '.xlsx']:
                return "excel"
            elif ext in ['.ppt', '.pptx']:
                return "powerpoint"
            else:
                return "file"


class FileTreeModel(QAbstractTableModel):
    """文件树数据模型类
    
    用于在表格视图中显示文件列表，支持多选、拖拽等功能
    """
    
    # 定义列索引
    COLUMN_NAME = 0
    COLUMN_SIZE = 1
    COLUMN_TIME = 2
    COLUMN_PERMISSIONS = 3
    COLUMN_OWNER = 4
    
    # 定义信号
    file_double_clicked = Signal(FileInfo)  # 文件双击信号
    selection_changed = Signal(list)  # 选择改变信号
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self._files = []  # 文件列表
        self._current_path = "/"  # 当前路径
        self._sort_column = -1  # 当前排序列
        self._sort_order = Qt.AscendingOrder  # 排序顺序
        
        # 列标题
        self._headers = ["名称", "大小", "修改时间", "权限", "拥有者"]
        
        logger.info("文件树模型初始化完成")
        
    def rowCount(self, parent=QModelIndex()):
        """返回行数"""
        return len(self._files)
        
    def columnCount(self, parent=QModelIndex()):
        """返回列数"""
        return len(self._headers)
        
    def headerData(self, section, orientation, role=Qt.DisplayRole):
        """返回表头数据"""
        if orientation == Qt.Horizontal:
            if role == Qt.DisplayRole:
                if 0 <= section < len(self._headers):
                    return self._headers[section]
            elif role == Qt.TextAlignmentRole:
                return Qt.AlignLeft | Qt.AlignVCenter
        return None
        
    def data(self, index, role=Qt.DisplayRole):
        """返回单元格数据"""
        if not index.isValid() or index.row() >= len(self._files):
            return None
            
        file_info = self._files[index.row()]
        column = index.column()
        
        if role == Qt.DisplayRole:
            if column == self.COLUMN_NAME:
                return file_info.name
            elif column == self.COLUMN_SIZE:
                return file_info.get_size_string()
            elif column == self.COLUMN_TIME:
                return file_info.get_time_string()
            elif column == self.COLUMN_PERMISSIONS:
                return file_info.permissions
            elif column == self.COLUMN_OWNER:
                return file_info.owner
                
        elif role == Qt.DecorationRole and column == self.COLUMN_NAME:
            # 返回文件图标
            icon_name = file_info.get_icon_name()
            try:
                return QIcon(f":/icon/{icon_name}.svg")
            except:
                return QIcon()  # 返回空图标
                
        elif role == Qt.UserRole:
            # 返回文件信息对象
            return file_info
            
        elif role == Qt.CheckStateRole and column == self.COLUMN_NAME:
            # 不显示复选框
            return None
            
        return None
        
    def lessThan(self, left, right):
        """用于排序的比较函数
        
        参数:
            left: 左侧索引
            right: 右侧索引
        """
        if not left.isValid() or not right.isValid():
            return False
            
        left_file = self._files[left.row()]
        right_file = self._files[right.row()]
        
        # 返回上级目录项始终在最前面
        if left_file.is_parent:
            return True
        if right_file.is_parent:
            return False
            
        column = left.column()
        
        # 目录优先于文件
        if left_file.is_directory != right_file.is_directory:
            return left_file.is_directory
            
        # 根据列类型进行比较
        if column == self.COLUMN_NAME:
            return left_file.name.lower() < right_file.name.lower()
        elif column == self.COLUMN_SIZE:
            return left_file.size < right_file.size
        elif column == self.COLUMN_TIME:
            return left_file.modified_time < right_file.modified_time
        elif column == self.COLUMN_PERMISSIONS:
            return left_file.permissions < right_file.permissions
        elif column == self.COLUMN_OWNER:
            return left_file.owner < right_file.owner
            
        return False
        
    def flags(self, index):
        """返回单元格标志"""
        if not index.isValid():
            return Qt.ItemIsDropEnabled  # 支持拖拽到空白区域
            
        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
        
        # 不再支持复选框
        return flags
        
    def setData(self, index, value, role=Qt.EditRole):
        """设置单元格数据"""
        if not index.isValid() or index.row() >= len(self._files):
            return False
        return False
        
    def supportedDropActions(self):
        """支持的拖拽操作"""
        return Qt.CopyAction | Qt.MoveAction
        
    def mimeTypes(self):
        """支持的MIME类型"""
        return ['text/uri-list']
        
    def dropMimeData(self, data, action, row, column, parent):
        """处理拖拽数据"""
        if not data.hasUrls():
            return False
            
        urls = data.urls()
        local_files = []
        
        for url in urls:
            if url.isLocalFile():
                local_path = url.toLocalFile()
                local_files.append(local_path)
                
        if local_files:
            # 发射文件上传信号（需要在视图中连接处理）
            logger.info(f"接收到拖拽文件: {local_files}")
            # 这里可以发射自定义信号，由视图处理文件上传
            
        return True
        
    def set_files(self, files, current_path="/"):
        """设置文件列表
        
        参数:
            files: FileInfo对象列表
            current_path: 当前路径
        """
        self.beginResetModel()
        
        self._files = []
        self._current_path = current_path
        
        # 如果不是根目录，添加返回上级目录项
        if current_path != "/":
            parent_item = FileInfo("..", 0, None, "", "", True, True)
            self._files.append(parent_item)
            
        # 添加文件列表
        self._files.extend(files)
        
        self.endResetModel()
        
        # 如果之前有排序设置，重新应用排序
        if self._sort_column >= 0:
            self.sort(self._sort_column, self._sort_order)
        
        logger.info(f"设置文件列表完成，共 {len(files)} 个文件，当前路径: {current_path}")
        
    def get_file_info(self, index):
        """获取指定索引的文件信息"""
        if 0 <= index < len(self._files):
            return self._files[index]
        return None
        
    def get_selected_files(self):
        """获取选中的文件列表（已弃用，使用视图的选择模型）"""
        # 这个方法已弃用，现在使用视图的选择模型
        return []
        
    def get_current_path(self):
        """获取当前路径"""
        return self._current_path
        
    def is_parent_directory(self, row):
        """检查指定行是否为返回上级目录项"""
        if 0 <= row < len(self._files):
            return self._files[row].is_parent
        return False
        
    def sort(self, column, order):
        """排序文件列表
        
        参数:
            column: 排序列索引
            order: 排序顺序 (Qt.AscendingOrder 或 Qt.DescendingOrder)
        """
        if column < 0 or column >= self.columnCount():
            return
            
        # 检查是否需要排序（避免重复排序）
        if self._sort_column == column and self._sort_order == order:
            logger.debug(f"排序状态未改变，跳过排序: 列{column}, {'升序' if order == Qt.AscendingOrder else '降序'}")
            return
            
        self._sort_column = column
        self._sort_order = order
        
        # 开始模型重置
        self.layoutAboutToBeChanged.emit()
        
        # 分离返回上级目录项和普通文件
        parent_items = []
        normal_files = []
        
        for file_info in self._files:
            if file_info.is_parent:
                parent_items.append(file_info)
            else:
                normal_files.append(file_info)
        
        # 对普通文件进行排序
        if normal_files:
            reverse_order = (order == Qt.DescendingOrder)
            
            if column == self.COLUMN_NAME:
                # 按名称排序，目录优先
                normal_files.sort(
                    key=lambda x: (not x.is_directory, x.name.lower()),
                    reverse=reverse_order
                )
            elif column == self.COLUMN_SIZE:
                # 按大小排序，目录大小为0
                normal_files.sort(
                    key=lambda x: (not x.is_directory, x.size),
                    reverse=reverse_order
                )
            elif column == self.COLUMN_TIME:
                # 按修改时间排序
                normal_files.sort(
                    key=lambda x: (not x.is_directory, x.modified_time),
                    reverse=reverse_order
                )
            elif column == self.COLUMN_PERMISSIONS:
                # 按权限排序
                normal_files.sort(
                    key=lambda x: (not x.is_directory, x.permissions),
                    reverse=reverse_order
                )
            elif column == self.COLUMN_OWNER:
                # 按拥有者排序
                normal_files.sort(
                    key=lambda x: (not x.is_directory, x.owner),
                    reverse=reverse_order
                )
        
        # 重新组合文件列表：返回上级目录项始终在最前面
        self._files = parent_items + normal_files
        
        # 完成模型重置
        self.layoutChanged.emit()
        
        logger.info(f"文件列表已按第{column}列{'降序' if order == Qt.DescendingOrder else '升序'}排序")
        
    def get_sort_info(self):
        """获取当前排序信息
        
        返回:
            tuple: (排序列, 排序顺序)
        """
        return (self._sort_column, self._sort_order)
        
    def clear_sort(self):
        """清除排序设置"""
        self._sort_column = -1
        self._sort_order = Qt.AscendingOrder
        logger.info("已清除排序设置")